<?php

//namespace IUPay;

class IUPay{
    const DOMAIN = 'https://pay.iuact.com';
    const QUERY_URL = 'https://pay.iuact.com/api/wechat/query';
    const WECHAT_NATIVE_URL = 'https://pay.iuact.com/api/wechat/native';
    const WECHAT_JSAPI_URL = 'https://pay.iuact.com/api/wechat/mp';

    public $appId;
    public $appSecret;
    public $subMchId;
    public $notify;
    public $client;

    public function __construct($config) {
        $this->appId = $config['app_key'];
        $this->appSecret = $config['app_secret'];
        $this->subMchId = $config['sub_mch_id'];
        $this->notify = $config['notify'];
        $timeout = isset($config['timeout']) ? $config['timeout'] : 10.0;
    }

    /**
     * @param $outTradeNo 自定义订单号
     * @param $subject 描述信息
     * @param $totalFee  总费用(单位分或带小数的元)
     * @param string $extra 订单自定义参数，回传
     * @param int $product_id 商品id，需要传
     * @return array|mixed
     */
    public function native($outTradeNo, $subject, $totalFee, $extra = '', $product_id=1) {
        $data = array(
            'app_key' => $this->appId,
            'out_trade_no' => $outTradeNo,
            'total_fee' => $totalFee,
            'subject' => $subject,
            'extra' => $extra,
            'notify_url' => $this->notify,
            'sub_mch_id' => $this->subMchId,
            'product_id' => $product_id,//自定义
        );
        $data['sign'] = Signer::getSign($data, $this->appSecret);
        return $this->request(self::WECHAT_NATIVE_URL, $data);
    }

    /**
     * @param $outTradeNo 自定义订单号
     * @param $subject 标题
     * @param $totalFee 总费用(单位分或带小数的元)
     * @param $openid
     * @param string $extra 订单自定义参数，回传
     * @return array|mixed
     */
    public function mp($outTradeNo, $subject, $totalFee, $openid, $extra = '') {
        $data = array(
            'app_key' => $this->appId,
            'openid' => $openid,
            'out_trade_no' => $outTradeNo,
            'total_fee' => $totalFee,
            'subject' => $subject,
            'extra' => $extra,
            'notify_url' => $this->notify,
            'sub_mch_id' => $this->subMchId,
        );
        $data['sign'] = Signer::getSign($data, $this->appSecret);
        return $this->request(self::WECHAT_JSAPI_URL, $data);
    }

    public function getOpenidUrl($callbackUrl) {
        return sprintf(DOMAIN.'/wechat/login?app_key=%s&sub_mch_id=%s&callback=%s', $this->appId, $this->subMchId, $callbackUrl);
    }

    public function callback(array $data) {
        if (! Signer::verify($data, $data['sign'], $this->appSecret)) {
            throw new \Exception('签名校验失败');
        }
        return $data;
    }

    public function queryUseOrderSn($orderSn) {
        $data = array(
            'app_key' => $this->appId,
            'order_sn' => $orderSn,
        );
        return $this->query($data);
    }

    /**
     * 查询订单详情
     * @param $val outTradeNo
     * @return array|mixed
     */
    public function queryUseOutTradeNo($outTradeNo) {
        $data = array(
            'app_key' => $this->appId,
            'out_trade_no' => $outTradeNo,
        );
        return $this->query($data);
    }

    public function queryUseOrderTransactionId($transactionId) {
        $data = array(
            'app_key' => $this->appId,
            'transaction_id' => $transactionId,
        );
        return $this->query($data);
    }

    public function query(array $data) {
        $data['sign'] = Signer::getSign($data, $this->appSecret);
        return $this->request(self::QUERY_URL, $data);
    }

    public function request($url, $data = null, $options = null) {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        if (!empty($data)) {
            curl_setopt($ch, CURLOPT_POST, 1);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        }
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0);
        is_array($options) && curl_setopt_array($ch, $options);
        $rs = curl_exec($ch);
        if ($err_no = curl_errno($ch)) {//出错则显示错误信息
            return array('errcode' => $err_no, 'msg' => 'CURL：' . curl_error($ch));
        } else {
            curl_close($ch);
            return json_decode($rs, true);
        }
    }
}

class Signer {
    // 获取签名
    public static function getSign($data, $appSecret) {
        ksort($data);
        $rows = array();
        foreach ($data as $key => $value) {
            if (! $value || $key == 'sign') {
                continue;
            }
            $rows[] = "{$key}={$value}";
        }
        $s = implode('&', $rows);
        $s .= $appSecret;
        return strtoupper(md5($s));
    }

    // 验证签名
    public static function verify($data, $sign, $appSecret) {
        return strtoupper($sign) === self::getSign($data, $appSecret);
    }
}




